/****************************************************
	文件：WndBase.cs
	作者：HuskyT
	邮箱：1005240602@qq.com
	日期：2020/10/4 20:52:0
	功能：UI窗口基类
*****************************************************/

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using HTFramework.ResKit;
using HTUtility;

namespace HTFramework.UIKit
{
    public class WndBase
    {
        public GameObject GameObject { get; set; }
        public Transform Transform { get; set; }
        public string PanelName { get; set; }
        public List<Button> BtnLst = new List<Button>();
        public List<Toggle> TogLst = new List<Toggle>();

        /// <summary>
        /// 获取 Panel
        /// </summary>
        /// <typeparam name="T">panel 类型</typeparam>
        /// <returns></returns>
        public T GetPanel<T>() where T : PanelBase
        {
            T panel = GameObject.GetComponent<T>();
            panel.Init();
            return panel;
        }
        /// <summary>
        /// 处理窗口消息
        /// </summary>
        /// <param name="msgType">UIManager中定义的消息类型</param>
        /// <param name="paramLst">参数列表</param>
        public virtual void OnWndMsg(WndMsgType msgType, params object[] paramLst) { }
        /// <summary>
        /// 同步设置 Image 图片
        /// </summary>
        /// <param name="spritePath">Sprite资源路径</param>
        /// <param name="img">Image组件</param>
        /// <param name="isSetNativeSize">是否设置为Sprite原尺寸</param>
        /// <returns></returns>
        public bool SetImgSpriteSync(string spritePath, Image img, bool isSetNativeSize = false)
        {
            if (img == null) return false;
            Sprite sprite = ResLoader.Instance.LoadSync<Sprite>(spritePath);
            if (sprite == null) return false;
            img.sprite = sprite;
            if (isSetNativeSize)
            {
                img.SetNativeSize();
            }
            return true;
        }
        /// <summary>
        /// 异步设置 Image 图片
        /// </summary>
        /// <param name="spritePath">Sprite资源路径</param>
        /// <param name="img">Image组件</param>
        /// <param name="isSetNativeSize">是否设置为Sprite原尺寸</param>
        public void SetImgSpriteAsync(string spritePath, Image img, bool isSetNativeSize = false)
        {
            if (img == null) return;
            ResLoader.Instance.LoadAsync(spritePath, (resItem) =>
            {
                if (resItem.Obj == null) return;
                Sprite sprite = resItem.Obj as Sprite;
                img.sprite = sprite;
                if (isSetNativeSize)
                {
                    img.SetNativeSize();
                }
            });
        }
        /// <summary>
        /// 添加 Button 监听
        /// </summary>
        /// <param name="btn">按钮</param>
        /// <param name="unityAction">按钮点击的监听事件</param>
        protected void AddBtnClick(Button btn, UnityEngine.Events.UnityAction unityAction)
        {
            if (btn != null)
            {
                if (BtnLst.Contains(btn) == false)
                {
                    BtnLst.Add(btn);
                }
                btn.onClick.RemoveAllListeners();
                btn.onClick.AddListener(unityAction);
                btn.onClick.AddListener(BtnPlaySound);
            }
        }
        /// <summary>
        /// 播放按钮点击音效
        /// </summary>
        protected virtual void BtnPlaySound() { }
        /// <summary>
        /// 添加 Toggle 监听
        /// </summary>
        /// <param name="tog">Toggle</param>
        /// <param name="unityAction">Toggle的监听事件</param>
        protected void AddToggleClick(Toggle tog, UnityEngine.Events.UnityAction<bool> unityAction)
        {
            if (tog != null)
            {
                if (TogLst.Contains(tog) == false)
                {
                    TogLst.Add(tog);
                }
                tog.onValueChanged.RemoveAllListeners();
                tog.onValueChanged.AddListener(unityAction);
                tog.onValueChanged.AddListener(TogPlaySound);
            }
        }
        /// <summary>
        /// 播放Toggle点击音效
        /// </summary>
        /// <param name="isOn">Toggle状态</param>
        protected virtual void TogPlaySound(bool isOn) { }

        /// <summary>
        /// 执行所有的事件注册（OnShow中调用）
        /// </summary>
        protected virtual void RegisterEvent()
        {
            HTLogger.Debug("注册wnd事件");
        }
        /// <summary>
        /// 执行所有的事件注销（OnHide中调用）
        /// </summary>
        protected virtual void UnRegisterEvent()
        {
            HTLogger.Debug("注销wnd事件");
            UnRegisterBtn();
            UnRegisterTog();
            UnsubscribeAllEvent();
        }
        /// <summary>
        /// 移除 Button 监听事件
        /// </summary>
        protected void UnRegisterBtn()
        {
            for (int i = 0; i < BtnLst.Count; i++)
            {
                BtnLst[i].onClick.RemoveAllListeners();
            }
            BtnLst.Clear();
        }
        /// <summary>
        /// 移除 Toggle 监听事件
        /// </summary>
        protected void UnRegisterTog()
        {
            for (int i = 0; i < TogLst.Count; i++)
            {
                TogLst[i].onValueChanged.RemoveAllListeners();
            }
            TogLst.Clear();
        }

        #region 生命周期
        public virtual void OnAwake(params object[] paramLst)
        {
            HTLogger.Debug("awake wnd");
        }
        public virtual void OnShow(params object[] paramLst)
        {
            HTLogger.Debug("show wnd");
            RegisterEvent();
        }
        public virtual void OnUpdate() { }
        public virtual void OnHide()
        {
            HTLogger.Debug("hide wnd");
            UnRegisterEvent();
        }
        public virtual void OnDestory()
        {
            HTLogger.Debug("destroy wnd");
        }
        #endregion

        #region 内部集成的事件系统（提供自动注销事件功能）
        /// <summary>
        /// 缓存所有注册的事件
        /// </summary>
        protected List<EventRecord> mEventRecordLst = new List<EventRecord>();
        /// <summary>
        /// 注册事件（此处使用的委托为参数数组，存在装拆箱消耗）
        /// </summary>
        /// <param name="eventType">事件类型</param>
        /// <param name="callBack">回调</param>
        protected void SubscribeEvent(HTUtility.EventType eventType, HTCallBack callBack)
        {
            EventCenter.Subscribe(eventType, callBack);
            EventRecord record = UIMgr.Instance.EventRecordPool.Spawn(true);
            record.EventType = eventType;
            record.CallBack = callBack;
            mEventRecordLst.Add(record);
        }
        /// <summary>
        /// 发送事件
        /// </summary>
        /// <param name="eventType">事件类型</param>
        /// <param name="args">回调参数</param>
        protected void FireEvent(HTUtility.EventType eventType, params object[] args)
        {
            EventCenter.Fire(eventType, args);
        }
        /// <summary>
        /// 注销指定事件类型下的指定事件
        /// </summary>
        /// <param name="eventType">事件类型</param>
        /// <param name="callBack">指定事件</param>
        protected void UnsubscribeEvent(HTUtility.EventType eventType, HTCallBack callBack)
        {
            List<EventRecord> result = mEventRecordLst.FindAll(record => record.EventType == eventType && record.CallBack == callBack);
            result.ForEach((record) =>
            {
                EventCenter.Unsubscribe(record.EventType, record.CallBack);
                mEventRecordLst.Remove(record);
                record.Reset();
                UIMgr.Instance.EventRecordPool.Recycle(record);
            });
        }
        /// <summary>
        /// 注销指定事件名中的所有事件
        /// </summary>
        /// <param name="eventType">事件类型</param>
        protected void UnsubscribeEvent(HTUtility.EventType eventType)
        {
            List<EventRecord> result = mEventRecordLst.FindAll(record => record.EventType == eventType);
            result.ForEach((record) =>
            {
                EventCenter.Unsubscribe(record.EventType, record.CallBack);
                mEventRecordLst.Remove(record);
                record.Reset();
                UIMgr.Instance.EventRecordPool.Recycle(record);
            });
        }
        /// <summary>
        /// 注销所有事件
        /// </summary>
        protected void UnsubscribeAllEvent()
        {
            foreach (EventRecord record in mEventRecordLst)
            {
                EventCenter.Unsubscribe(record.EventType, record.CallBack);
                record.Reset();
                UIMgr.Instance.EventRecordPool.Recycle(record);
            }
            mEventRecordLst.Clear();
        }
        #endregion
    }
}
